@yaebal/rich 0.0.1 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/README.md +109 -35
  2. package/lib/blocks.d.ts +93 -32
  3. package/lib/blocks.d.ts.map +1 -1
  4. package/lib/blocks.js +227 -71
  5. package/lib/blocks.js.map +1 -1
  6. package/lib/blocks.test.d.ts +2 -0
  7. package/lib/blocks.test.d.ts.map +1 -0
  8. package/lib/blocks.test.js +142 -0
  9. package/lib/blocks.test.js.map +1 -0
  10. package/lib/document.d.ts +28 -0
  11. package/lib/document.d.ts.map +1 -0
  12. package/lib/document.js +46 -0
  13. package/lib/document.js.map +1 -0
  14. package/lib/draft.d.ts +46 -9
  15. package/lib/draft.d.ts.map +1 -1
  16. package/lib/draft.js +115 -19
  17. package/lib/draft.js.map +1 -1
  18. package/lib/draft.test.d.ts +2 -0
  19. package/lib/draft.test.d.ts.map +1 -0
  20. package/lib/draft.test.js +122 -0
  21. package/lib/draft.test.js.map +1 -0
  22. package/lib/escape.d.ts +8 -0
  23. package/lib/escape.d.ts.map +1 -1
  24. package/lib/escape.js +17 -0
  25. package/lib/escape.js.map +1 -1
  26. package/lib/escape.test.d.ts +2 -0
  27. package/lib/escape.test.d.ts.map +1 -0
  28. package/lib/escape.test.js +28 -0
  29. package/lib/escape.test.js.map +1 -0
  30. package/lib/guards.test.d.ts +2 -0
  31. package/lib/guards.test.d.ts.map +1 -0
  32. package/lib/guards.test.js +85 -0
  33. package/lib/guards.test.js.map +1 -0
  34. package/lib/index.d.ts +18 -9
  35. package/lib/index.d.ts.map +1 -1
  36. package/lib/index.js +17 -8
  37. package/lib/index.js.map +1 -1
  38. package/lib/index.test.js +73 -103
  39. package/lib/index.test.js.map +1 -1
  40. package/lib/inline.d.ts +48 -59
  41. package/lib/inline.d.ts.map +1 -1
  42. package/lib/inline.js +87 -82
  43. package/lib/inline.js.map +1 -1
  44. package/lib/inline.test.d.ts +2 -0
  45. package/lib/inline.test.d.ts.map +1 -0
  46. package/lib/inline.test.js +84 -0
  47. package/lib/inline.test.js.map +1 -0
  48. package/lib/node.d.ts +25 -0
  49. package/lib/node.d.ts.map +1 -0
  50. package/lib/node.js +21 -0
  51. package/lib/node.js.map +1 -0
  52. package/lib/plaintext.test.d.ts +2 -0
  53. package/lib/plaintext.test.d.ts.map +1 -0
  54. package/lib/plaintext.test.js +100 -0
  55. package/lib/plaintext.test.js.map +1 -0
  56. package/lib/render.d.ts +17 -0
  57. package/lib/render.d.ts.map +1 -0
  58. package/lib/render.js +30 -0
  59. package/lib/render.js.map +1 -0
  60. package/lib/send.d.ts +6 -3
  61. package/lib/send.d.ts.map +1 -1
  62. package/lib/send.js +12 -3
  63. package/lib/send.js.map +1 -1
  64. package/lib/template.d.ts +46 -0
  65. package/lib/template.d.ts.map +1 -0
  66. package/lib/template.js +82 -0
  67. package/lib/template.js.map +1 -0
  68. package/lib/template.test.d.ts +2 -0
  69. package/lib/template.test.d.ts.map +1 -0
  70. package/lib/template.test.js +78 -0
  71. package/lib/template.test.js.map +1 -0
  72. package/package.json +5 -4
  73. package/src/blocks.test.ts +233 -0
  74. package/src/blocks.ts +304 -86
  75. package/src/document.ts +51 -0
  76. package/src/draft.test.ts +167 -0
  77. package/src/draft.ts +148 -21
  78. package/src/escape.test.ts +38 -0
  79. package/src/escape.ts +20 -0
  80. package/src/guards.test.ts +138 -0
  81. package/src/index.test.ts +79 -140
  82. package/src/index.ts +26 -11
  83. package/src/inline.test.ts +125 -0
  84. package/src/inline.ts +131 -97
  85. package/src/node.ts +43 -0
  86. package/src/plaintext.test.ts +141 -0
  87. package/src/render.ts +54 -0
  88. package/src/send.ts +17 -10
  89. package/src/template.test.ts +100 -0
  90. package/src/template.ts +115 -0
  91. package/lib/message.d.ts +0 -26
  92. package/lib/message.d.ts.map +0 -1
  93. package/lib/message.js +0 -31
  94. package/lib/message.js.map +0 -1
  95. package/src/message.ts +0 -45
package/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # @yaebal/rich
2
2
 
3
- `sendRichMessage` / `sendRichMessageDraft` — telegram's block-tree message format. a typed builder for the extended html dialect, a draft/streaming session that owns the 30s ttl, and full read-side coverage (type guards + plain-text flattening) of everything telegram can hand back on `message.rich_message`.
3
+ `sendRichMessage` / `sendRichMessageDraft` — telegram's block-tree message format. one dual-dialect builder set, a draft/streaming session that owns the 30s ttl, and full read-side coverage (type guards + plain-text flattening) of everything telegram can hand back on `message.rich_message`.
4
4
 
5
- unlike classic `parse_mode`/entities (see [`@yaebal/fmt`](https://www.npmjs.com/package/@yaebal/fmt)), a rich message isn't a flat `{ text, entities }` pair — it's a document: paragraphs, headings, tables, lists, collages, slideshows, block quotes, a collapsible `<details>`, even a `<tg-thinking>` placeholder for streaming an in-progress answer. you write extended html (or markdown), telegram parses it server-side into a `RichMessage.blocks` tree, and that same tree is what you read back.
5
+ unlike classic `parse_mode`/entities (see [`@yaebal/fmt`](https://npmx.dev/package/@yaebal/fmt)), a rich message isn't a flat `{ text, entities }` pair — it's a document: paragraphs, headings, tables, lists, collages, slideshows, block quotes, a collapsible `<details>`, even a `<tg-thinking>` placeholder for streaming an in-progress answer. you write extended html (or markdown), telegram parses it server-side into a `RichMessage.blocks` tree, and that same tree is what you read back.
6
6
 
7
7
  ## install
8
8
 
@@ -10,54 +10,109 @@ unlike classic `parse_mode`/entities (see [`@yaebal/fmt`](https://www.npmjs.com/
10
10
  pnpm add @yaebal/rich
11
11
  ```
12
12
 
13
- ## sending
13
+ ## one builder, two dialects
14
+
15
+ telegram accepts a rich message as either `InputRichMessage.html` or `.markdown`. most rich-message libraries pick one dialect to build for and bolt the other on as a parallel, hand-duplicated set of functions. `@yaebal/rich` doesn't: every builder — `bold`, `paragraph`, `table`, `list`, all ~40 of them — returns a `RichNode` that doesn't know its own output format yet. it renders itself only when it lands inside a template:
16
+
17
+ ```ts
18
+ import { html, md, heading, paragraph, bold, link, sendRichMessage } from "@yaebal/rich";
19
+
20
+ const title = "release notes";
21
+ const body = [
22
+ heading(1, title),
23
+ paragraph("yaebal ", bold("0.1"), " is out — see ", link("https://yaebal.pages.dev", "the docs"), "."),
24
+ ];
25
+
26
+ await sendRichMessage(ctx.api, ctx.chat.id, html(body)); // <h1>…</h1><p>…</p>
27
+ await sendRichMessage(ctx.api, ctx.chat.id, md(body)); // # …\n\n…
28
+ ```
29
+
30
+ there is no `md.bold`/`md.paragraph` shadow api to learn, nothing to keep in sync, and nothing that silently drifts between dialects — `bold(...)` is `bold(...)` everywhere. `html`/`md` are tagged templates first:
14
31
 
15
32
  ```ts
16
- import { document, heading, paragraph, bold, link, sendRichMessage } from "@yaebal/rich";
33
+ const doc = html`
34
+ ${heading(1, title)}
17
35
 
18
- const input = document([
19
- heading(1, "release notes"),
20
- paragraph("yaebal ", bold("0.1"), " is out — see ", link("https://yaeb.al", "the docs"), "."),
21
- ]);
36
+ ${paragraph("yaebal ", bold("0.1"), " is out — see ", link("https://yaebal.pages.dev", "the docs"), ".")}
37
+ `;
22
38
 
23
- await sendRichMessage(ctx.api, ctx.chat.id, input);
39
+ await sendRichMessage(ctx.api, ctx.chat.id, doc);
24
40
  ```
25
41
 
26
- or install the plugin for `ctx.send`-flavored ergonomics:
42
+ literal template text passes through unchanged; only `${…}` interpolation is touched:
43
+
44
+ | interpolation | what happens |
45
+ |:----------------------------------------|:-------------------------------------------------------------------|
46
+ | `${string}` / `${number}` / `${bigint}` | dialect-escaped — renders literally, can't inject formatting |
47
+ | `${builderNode}` | rendered into the template's dialect |
48
+ | `${anotherDocument}` | inlined as-is if dialects match, throws `RichError` if they don't |
49
+ | `${array}` | each item rendered and concatenated |
50
+ | `${null \| undefined \| false}` | empty string — so `cond && bold("x")` composes cleanly |
51
+
52
+ multi-line templates are **dedented** (common leading indentation stripped) so you can write at your code's natural indent level. `html`/`md` also accept a plain string (passed through as-is, no escaping/dedent — for already-formatted content) or an array of blocks (each rendered and, for markdown, blank-line-joined — the form to reach for when composing from data instead of prose):
53
+
54
+ ```ts
55
+ html([heading(1, title), list(items.map((i) => paragraph(i.text)))]);
56
+ ```
57
+
58
+ `document(blocks, { dialect, rtl, skipEntityDetection })` is the options-object equivalent of `html(blocks)`/`md(blocks)`, for when the dialect is a runtime variable rather than a call-site choice.
59
+
60
+ ### `RichDocument` — the sendable result
61
+
62
+ `html`/`md`/`document()` all return a `RichDocument`: a rendered string plus the `InputRichMessage` flags, settable fluently.
63
+
64
+ ```ts
65
+ const doc = html`${paragraph("right-to-left, no auto-linking")}`
66
+ .rtl()
67
+ .noEntityDetection();
68
+
69
+ await sendRichMessage(ctx.api, ctx.chat.id, doc);
70
+ ```
71
+
72
+ `sendRichMessage`/`sendRichMessageDraft`/`RichMessageDraft` all accept a `RichDocument`, a raw `InputRichMessage`, or a plain html string interchangeably — `toJSON()` also delegates to `toInputRichMessage()`, so a `RichDocument` serializes correctly even nested inside a hand-built payload.
73
+
74
+ ### install the plugin for `ctx.send`-flavored ergonomics
27
75
 
28
76
  ```ts
29
77
  import { Bot } from "@yaebal/core";
30
- import { rich, document, paragraph } from "@yaebal/rich";
78
+ import { rich, html, paragraph } from "@yaebal/rich";
31
79
 
32
80
  const bot = new Bot(token)
33
81
  .install(rich())
34
- .command("hi", (ctx) => ctx.sendRichMessage(document([paragraph("hello!")])));
82
+ .command("hi", (ctx) => ctx.sendRichMessage(html`${paragraph("hello!")}`));
35
83
  ```
36
84
 
37
85
  ## streaming a draft
38
86
 
39
87
  `sendRichMessageDraft` streams a partial answer to a private chat — but the draft is **ephemeral**: telegram drops it 30 seconds after the last push, and it never becomes a real message on its own. `RichMessageDraft` owns that lifecycle: it re-pushes the latest draft on a timer so a slow generator doesn't lose it, and it refuses to push after you close it.
40
88
 
89
+ two ways to grow a draft: `rewrite()` replaces the whole thing — right for a token stream, where every chunk is a longer version of the *same* paragraph. `write()` appends to it (plain string concatenation) — right for tacking on a block after content that's already there, without re-supplying it.
90
+
41
91
  ```ts
42
- import { thinking, document, paragraph, sendRichMessage } from "@yaebal/rich";
92
+ import { thinking, html, paragraph, divider, footer } from "@yaebal/rich";
43
93
 
44
94
  bot.command("ask", async (ctx) => {
45
95
  const draft = ctx.richMessageDraft(1); // draft_id, non-zero, per-message
46
96
 
47
- await draft.push(thinking("thinking…")); // draft-only block, see below
97
+ await draft.rewrite(html`${thinking("thinking…")}`); // draft-only block, see below
48
98
 
49
99
  let text = "";
50
100
  for await (const chunk of streamAnswer(ctx.text)) {
51
101
  text += chunk;
52
- await draft.push(document([paragraph(text)]));
102
+ await draft.rewrite(html`${paragraph(text)}`);
53
103
  }
54
104
 
55
- // required: a draft never persists on its own.
56
- await draft.commit(document([paragraph(text)]));
105
+ await draft.write(html`${divider()}${footer("streamed")}`); // append, no need to re-supply `text`
106
+
107
+ // required: a draft never persists on its own. send() with no argument
108
+ // auto-assembles from the rewrite()/write() calls above; pass an explicit
109
+ // override (as here) when the persisted message should differ from the last
110
+ // draft snapshot.
111
+ await draft.send(html`${paragraph(text.trim())}${divider()}${footer("streamed")}`);
57
112
  });
58
113
  ```
59
114
 
60
- call `draft.cancel()` instead of `commit()` to abandon a draft without persisting anything (it expires within 30s regardless).
115
+ call `draft.cancel()` instead of `send()` to abandon a draft without persisting anything (it expires within 30s regardless).
61
116
 
62
117
  ## reading
63
118
 
@@ -76,31 +131,50 @@ bot.on("message:rich_message", (ctx) => {
76
131
 
77
132
  every one of telegram's ~50 `Rich*` types is covered on both sides:
78
133
 
79
- - **write** — a builder function (or documented auto-detection) for every block and inline mark.
134
+ - **write** — a builder function (or documented auto-detection) for every block and inline mark, in both dialects at once.
80
135
  - **read** — an `isX` type guard and a plain-text flattening branch for every block and inline mark.
81
136
 
82
- most tags are **confirmed** directly from telegram's schema (`<p>`, `<h1>`–`<h6>`, `<pre><code>`, `<hr/>`, `<footer>`, `<blockquote>`, `<aside>` for pull-quotes, `<details>`/`<summary>`, `<table>`, `<tg-collage>`, `<tg-slideshow>`, `<tg-map>`, `<tg-math-block>`, `<tg-thinking>`, `<img>`/`<video>`/`<audio>`, `<a name>`/`<a href="#…">`, `<cite>`, and the classic `<b>`/`<i>`/`<u>`/`<s>`/`<code>`/`<tg-spoiler>`/`<tg-emoji>`/`tg://user?id=…` set). `url`/`email_address`/`phone_number`/`bank_card_number`/`@mention`/`#hashtag`/`$cashtag`/`/bot_command` need **no explicit tag at all** — telegram auto-detects them from plain text unless you pass `skipEntityDetection: true`.
137
+ most tags are **confirmed** directly from telegram's schema (`<p>`, `<h1>`–`<h6>`, `<pre><code>`, `<hr/>`, `<footer>`, `<blockquote>`, `<aside>` for pull-quotes, `<details>`/`<summary>`, `<table>`, `<tg-collage>`, `<tg-slideshow>`, `<tg-map>`, `<tg-math-block>`, `<tg-thinking>`, `<img>`/`<video>`/`<audio>`, `<a name>`/`<a href="#…">`, `<cite>`, and the classic `<b>`/`<i>`/`<u>`/`<s>`/`<code>`/`<tg-spoiler>`/`<tg-emoji>`/`tg://user?id=…` set). `url`/`email_address`/`phone_number`/`bank_card_number`/`@mention`/`#hashtag`/`$cashtag`/`/bot_command` need **no explicit tag at all** — telegram auto-detects them from plain text unless you pass `.noEntityDetection()`.
83
138
 
84
- a handful of inline/block features have **no documented tag** in the schema at all (`marked`, `subscript`, `superscript`, `date_time`, inline `mathematical_expression`, `reference`/`reference_link`, table `is_bordered`/`is_striped`). those are implemented as a best-effort guess (standard html5 tags where one exists, a `tg-*`-style name otherwise) and flagged in their doc comments in `inline.ts`/`blocks.ts` — verify against the live "rich message formatting options" docs before relying on the exact spelling in production.
139
+ a handful of inline/block features have **no documented tag** in the schema at all (`marked`, `subscript`, `superscript`, `date_time`, inline `mathematical_expression`, `reference`/`reference_link`, table `is_bordered`/`is_striped`). those are implemented as a best-effort guess (standard html5 tags where one exists, a `tg-*`-style name otherwise) and flagged in their doc comments in `inline.ts`/`blocks.ts` — verify against the live "rich message formatting options" docs before relying on the exact spelling in production. where rich-markdown has no native token for a block at all (`footer`, pull-quote, collage/slideshow, map, `details`, `underline`, `subscript`, `superscript`), the raw html tag is embedded as-is in the markdown output too — telegram's markdown parser accepts embedded html blocks as long as they're blank-line-separated, which the block builders already handle.
85
140
 
86
141
  `sendRichMessage` has no `attach://`/multipart upload path (unlike `sendPhoto`) — media blocks (`image`/`video`/`audio`) take a hosted url, not a local file.
87
142
 
143
+ ### tables and lists carry their full field set
144
+
145
+ `cell()` and `item()` aren't afterthoughts bolted onto a plain-array api — they're first-class `RichNode`s that also carry the options `table()`/`list()` need to do the right thing per dialect:
146
+
147
+ ```ts
148
+ table(
149
+ [
150
+ [cell("day", { header: true }), cell("count", { header: true, align: "right" })],
151
+ [cell("mon"), cell(128, { align: "right", colspan: 2 })],
152
+ ],
153
+ { bordered: true, caption: "week" },
154
+ );
155
+ ```
156
+
157
+ in html this is a full `<table>` with `colspan`/`rowspan`/`valign`/per-cell `<th>`/`<td>`; in markdown it degrades gracefully to a gfm table (structurally header-first, alignment preserved, the rest dropped — gfm has no cell spans). `list()` accepts bare values directly (auto-wrapped in a plain item) or explicit `item()`s for checkboxes and ordered-list numbering overrides (`value`, `type`) — no separate wrapper step required either way.
158
+
88
159
  ## api
89
160
 
90
- | export | what |
91
- |:-------------------------------------------------------------------------------------------------------|:--------------------------------------------------------------------------|
92
- | `html` | tagged template for the extended-html dialect, auto-escaped interpolation |
93
- | `bold`/`italic`/`underline`/`strikethrough`/`spoiler`/`code`/`marked`/`subscript`/`superscript` | inline marks |
94
- | `link`/`textMention`/`anchor`/`anchorLink`/`customEmoji`/`dateTime`/`math`/`reference`/`referenceLink` | inline nodes with data |
95
- | `paragraph`/`heading`/`preformatted`/`footer`/`divider`/`mathBlock`/`anchorBlock` | simple blocks |
96
- | `blockquote`/`pullquote`/`details`/`list`/`item`/`table`/`cell` | structural blocks |
97
- | `collage`/`slideshow`/`map`/`image`/`video`/`audio`/`thinking` | media & draft-only blocks |
98
- | `document`/`markdown` | assemble blocks into an `InputRichMessage` |
99
- | `sendRichMessage`/`sendRichMessageDraft` | standalone send functions, no plugin required |
100
- | `rich()` | plugin: adds `ctx.sendRichMessage`/`ctx.richMessageDraft` |
101
- | `RichMessageDraft` | the draft/streaming session class |
102
- | `isParagraph`, `isTable`, `isCustomEmoji`, … | one type guard per `RichBlock`/`RichText` variant |
103
- | `richTextToPlainText`/`richBlockToPlainText`/`richMessageToPlainText` | flatten to plain text |
161
+ | export | what |
162
+ |:-------------------------------------------------------------------------------------------------------|:-----------------------------------------------------------------------------------------|
163
+ | `html` / `md` | tagged templates same builders, either dialect, auto-escaped interpolation |
164
+ | `document` | options-object form: assemble blocks into a `RichDocument` with an explicit dialect |
165
+ | `RichDocument` | the sendable result — `.rtl()`/`.noEntityDetection()`, `toInputRichMessage()`/`toJSON()` |
166
+ | `bold`/`italic`/`underline`/`strikethrough`/`spoiler`/`code`/`marked`/`subscript`/`superscript`/`br` | inline marks |
167
+ | `link`/`textMention`/`anchor`/`anchorLink`/`customEmoji`/`dateTime`/`math`/`reference`/`referenceLink` | inline nodes with data |
168
+ | `paragraph`/`heading`/`h1`–`h6`/`preformatted`/`footer`/`divider`/`mathBlock`/`anchorBlock` | simple blocks |
169
+ | `blockquote`/`pullquote`/`details`/`list`/`item`/`table`/`cell`/`join` | structural blocks & composition |
170
+ | `collage`/`slideshow`/`map`/`image`/`video`/`audio`/`thinking` | media & draft-only blocks |
171
+ | `RichNode`/`isRichNode`/`makeNode`/`Dialect`/`Level`/`RichError` | the node contract, for writing your own dual-dialect builder |
172
+ | `escapeMarkdown`/`escapeMarkdownUrl` | the raw markdown escapers the builders use internally |
173
+ | `sendRichMessage`/`sendRichMessageDraft` | standalone send functions, no plugin required |
174
+ | `rich()` | plugin: adds `ctx.sendRichMessage`/`ctx.richMessageDraft` |
175
+ | `RichMessageDraft` | the draft/streaming session class — `rewrite()`/`write()`/`send()`/`cancel()` |
176
+ | `isParagraph`, `isTable`, `isCustomEmoji`, … | one type guard per `RichBlock`/`RichText` variant |
177
+ | `richTextToPlainText`/`richBlockToPlainText`/`richMessageToPlainText` | flatten to plain text |
104
178
 
105
179
  plus the full generated type surface (`RichMessage`, `RichBlock`, `RichText`, and every `RichBlock*`/`RichText*` interface) re-exported from `@yaebal/types` for convenience.
106
180
 
package/lib/blocks.d.ts CHANGED
@@ -1,75 +1,128 @@
1
- import { type Insertable, type RichNode } from "./inline.js";
1
+ import { type RichNode } from "./node.js";
2
+ import { type Insertable } from "./render.js";
2
3
  /** a caption + optional credit for a media/collage/slideshow/map block (`RichBlockCaption`). */
3
4
  export interface Caption {
4
5
  caption?: Insertable;
5
6
  /** `RichBlockCaption.credit`, confirmed `<cite>`. */
6
7
  credit?: Insertable;
7
8
  }
8
- /** `RichBlockParagraph`, `<p>`. */
9
- export declare function paragraph(...children: Insertable[]): RichNode;
10
- /** `RichBlockSectionHeading`, `<h1>`–`<h6>`. `level` is telegram's `size` (1 largest, 6 smallest). */
11
- export declare function heading(level: 1 | 2 | 3 | 4 | 5 | 6, ...children: Insertable[]): RichNode;
12
- /** `RichBlockPreformatted`, nested `<pre><code>`, matching classic parse_mode html. */
9
+ /** `RichBlockParagraph` `<p>` in html, bare text in markdown (blocks are blank-line-joined). */
10
+ export declare function paragraph(...items: Insertable[]): RichNode;
11
+ /** `RichBlockSectionHeading` `<h1>`–`<h6>` / `#`–`######`. `level` is telegram's `size` (1 largest). */
12
+ export declare function heading(level: 1 | 2 | 3 | 4 | 5 | 6, ...items: Insertable[]): RichNode;
13
+ /** `heading(1, …)`. */
14
+ export declare const h1: (...items: Insertable[]) => RichNode;
15
+ /** `heading(2, …)`. */
16
+ export declare const h2: (...items: Insertable[]) => RichNode;
17
+ /** `heading(3, …)`. */
18
+ export declare const h3: (...items: Insertable[]) => RichNode;
19
+ /** `heading(4, …)`. */
20
+ export declare const h4: (...items: Insertable[]) => RichNode;
21
+ /** `heading(5, …)`. */
22
+ export declare const h5: (...items: Insertable[]) => RichNode;
23
+ /** `heading(6, …)`. */
24
+ export declare const h6: (...items: Insertable[]) => RichNode;
25
+ /**
26
+ * `RichBlockPreformatted` — nested `<pre><code>` (matching classic parse_mode
27
+ * html) / a fenced code block. `text` is raw code: html-escaped in the html
28
+ * dialect, emitted verbatim inside the markdown fence.
29
+ */
13
30
  export declare function preformatted(text: string, language?: string): RichNode;
14
- /** `RichBlockFooter`, `<footer>`. */
15
- export declare function footer(...children: Insertable[]): RichNode;
16
- /** `RichBlockDivider`, `<hr/>`. */
31
+ /** `RichBlockFooter` `<footer>`; no markdown token, raw tag embedded there too. */
32
+ export declare function footer(...items: Insertable[]): RichNode;
33
+ /** `RichBlockDivider` `<hr/>` / `---`. */
17
34
  export declare function divider(): RichNode;
18
- /** `RichBlockMathematicalExpression`, confirmed `<tg-math-block>` (LaTeX). */
35
+ /** `RichBlockMathematicalExpression` confirmed `<tg-math-block>` / `$$…$$` (raw LaTeX, unescaped in markdown). */
19
36
  export declare function mathBlock(expression: string): RichNode;
20
- /** `RichBlockAnchor`, `<a name="…">` at block level. */
37
+ /** `RichBlockAnchor` `<a name="…">` at block level, in both dialects. */
21
38
  export declare function anchorBlock(name: string): RichNode;
22
- /** `RichBlockBlockQuotation`, `<blockquote>`, with an optional `<cite>` credit. */
23
- export declare function blockquote(children: Insertable[], credit?: Insertable): RichNode;
24
- /** `RichBlockPullQuotation`, loosely `<aside>` per the schema, with an optional `<cite>` credit. */
39
+ /**
40
+ * `RichBlockBlockQuotation` — `<blockquote>` with an optional `<cite>` credit;
41
+ * `>`-prefixed lines in markdown (each array item becomes its own line, the
42
+ * credit a trailing `> — credit` line).
43
+ */
44
+ export declare function blockquote(items: Insertable[], credit?: Insertable): RichNode;
45
+ /** `RichBlockPullQuotation` — loosely `<aside>` per the schema, with an optional `<cite>` credit. */
25
46
  export declare function pullquote(text: Insertable, credit?: Insertable): RichNode;
26
- /** `RichBlockCollage`, confirmed custom tag `<tg-collage>`. */
47
+ /** `RichBlockCollage` confirmed custom tag `<tg-collage>` (raw in markdown too). */
27
48
  export declare function collage(blocks: Insertable[], caption?: Caption): RichNode;
28
- /** `RichBlockSlideshow`, confirmed custom tag `<tg-slideshow>`. */
49
+ /** `RichBlockSlideshow` confirmed custom tag `<tg-slideshow>` (raw in markdown too). */
29
50
  export declare function slideshow(blocks: Insertable[], caption?: Caption): RichNode;
51
+ declare const TABLE_CELL: unique symbol;
30
52
  export interface TableCellOptions {
53
+ /** `<th>` instead of `<td>`. html-only — gfm's header is structural (see `table`). */
31
54
  header?: boolean;
55
+ /** html-only — gfm has no cell spans. */
32
56
  colspan?: number;
57
+ /** html-only — gfm has no cell spans. */
33
58
  rowspan?: number;
34
- /** default `"left"`, matching `RichBlockTableCell.align`. */
59
+ /** default `"left"`, matching `RichBlockTableCell.align`. feeds gfm's column alignment row. */
35
60
  align?: "left" | "center" | "right";
36
- /** default `"top"`, matching `RichBlockTableCell.valign`. */
61
+ /** default `"top"`, matching `RichBlockTableCell.valign`. html-only. */
37
62
  valign?: "top" | "middle" | "bottom";
38
63
  }
64
+ /** one table cell — a `RichNode` carrying its options so `table()` can read the gfm alignment. */
65
+ export interface TableCell extends RichNode {
66
+ readonly [TABLE_CELL]: true;
67
+ readonly align?: "left" | "center" | "right";
68
+ }
39
69
  /** one `<td>`/`<th>` cell; `content` omitted ⇒ an invisible cell (per `RichBlockTableCell`). */
40
- export declare function cell(content?: Insertable, options?: TableCellOptions): RichNode;
70
+ export declare function cell(content?: Insertable, options?: TableCellOptions): TableCell;
41
71
  export interface TableOptions {
42
- /** best-effort: rendered as the `border` attribute. */
72
+ /** best-effort: rendered as the `border` attribute. html-only. */
43
73
  bordered?: boolean;
44
- /** best-effort: no standard html equivalent, rendered as `data-striped`. */
74
+ /** best-effort: no standard html equivalent, rendered as `data-striped`. html-only. */
45
75
  striped?: boolean;
76
+ /** `<caption>` in html; a leading caption line in markdown. */
46
77
  caption?: Insertable;
47
78
  }
48
- /** `RichBlockTable`, confirmed `<table>`. build rows with `cell()`. */
79
+ /**
80
+ * `RichBlockTable`, confirmed `<table>` / a gfm table. build cells with `cell()`
81
+ * (a bare value is wrapped in a plain `cell()` automatically). gfm structurally
82
+ * requires a header row, so in markdown `rows[0]` always renders as the header
83
+ * line and `colspan`/`rowspan`/`valign`/`header`/`bordered`/`striped` are
84
+ * dropped; in html the header is per-cell opt-in (`cell(x, { header: true })`).
85
+ */
49
86
  export declare function table(rows: Insertable[][], options?: TableOptions): RichNode;
50
87
  export interface DetailsOptions {
51
88
  /** `RichBlockDetails.is_open` — content visible by default. defaults to `false`. */
52
89
  open?: boolean;
53
90
  }
54
- /** `RichBlockDetails`, confirmed `<details>`/`<summary>`. */
91
+ /**
92
+ * `RichBlockDetails`, confirmed `<details>`/`<summary>` (an html-only tag, legal
93
+ * inside markdown too — there the body must be blank-line-separated or telegram
94
+ * renders it as literal text).
95
+ */
55
96
  export declare function details(summary: Insertable, blocks: Insertable[], options?: DetailsOptions): RichNode;
97
+ declare const LIST_ITEM: unique symbol;
56
98
  export interface ListItemOptions {
57
99
  /** an unchecked/checked checkbox prefix (`RichBlockListItem.has_checkbox`/`is_checked`). */
58
100
  checkbox?: boolean;
59
101
  checked?: boolean;
60
- /** ordered-list numeric override (`RichBlockListItem.value`) — standard `<li value>`. */
102
+ /** ordered-list numeric override (`RichBlockListItem.value`) — standard `<li value>`; restarts gfm numbering. */
61
103
  value?: number;
62
- /** ordered-list label style override (`RichBlockListItem.type`) — standard `<li type>`. */
104
+ /** ordered-list label style override (`RichBlockListItem.type`) — standard `<li type>`. html-only. */
63
105
  type?: "a" | "A" | "i" | "I";
64
106
  }
65
- /** one `<li>` for `list()`. */
66
- export declare function item(blocks: Insertable[], options?: ListItemOptions): RichNode;
107
+ /** one list item — a `RichNode` carrying its options so `list()` can number/prefix it. */
108
+ export interface ListItem extends RichNode {
109
+ readonly [LIST_ITEM]: true;
110
+ readonly value?: number;
111
+ }
112
+ /** one `<li>` for `list()` — only needed when a plain value isn't enough (checkbox, value, type). */
113
+ export declare function item(blocks: Insertable[], options?: ListItemOptions): ListItem;
67
114
  export interface ListOptions {
68
115
  /** `<ol>` instead of `<ul>`. defaults to `false`. */
69
116
  ordered?: boolean;
117
+ /** first number of an ordered list — standard `<ol start>` / the first gfm marker. */
118
+ start?: number;
70
119
  }
71
- /** `RichBlockList`, `<ul>`/`<ol>` of `item()`s. */
72
- export declare function list(items: Insertable[], options?: ListOptions): RichNode;
120
+ /**
121
+ * `RichBlockList` `<ul>`/`<ol>` / `- `/`1. ` lines. entries may be plain
122
+ * values (wrapped in a default `item()` automatically) or explicit `item()`s
123
+ * for checkboxes and numbering overrides.
124
+ */
125
+ export declare function list(entries: Insertable[], options?: ListOptions): RichNode;
73
126
  export interface MapOptions {
74
127
  /** 13–20, per `RichBlockMap.zoom`. */
75
128
  zoom: number;
@@ -77,8 +130,9 @@ export interface MapOptions {
77
130
  height: number;
78
131
  }
79
132
  /**
80
- * `RichBlockMap`, confirmed custom tag `<tg-map>` attribute names/encoding are a
81
- * best-effort guess (lat/long/zoom/width/height are telegram's own field names).
133
+ * `RichBlockMap`, confirmed custom tag `<tg-map>` (raw in markdown too)
134
+ * attribute names/encoding are a best-effort guess (lat/long/zoom/width/height
135
+ * are telegram's own field names).
82
136
  */
83
137
  export declare function map(location: {
84
138
  latitude: number;
@@ -111,5 +165,12 @@ export declare function audio(src: string, options?: MediaOptions): RichNode;
111
165
  * schema states it can be used in `sendRichMessageDraft` payloads but is never
112
166
  * received back on a real message. see `RichMessageDraft` in draft.ts.
113
167
  */
114
- export declare function thinking(...children: Insertable[]): RichNode;
168
+ export declare function thinking(...items: Insertable[]): RichNode;
169
+ /**
170
+ * join content with a separator. if any entry is a block, the result is a block
171
+ * and entries are blank-line-joined (markdown) / concatenated (html) — the
172
+ * separator only applies to all-inline joins.
173
+ */
174
+ export declare function join(entries: Insertable[], separator?: Insertable): RichNode;
175
+ export {};
115
176
  //# sourceMappingURL=blocks.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"blocks.d.ts","sourceRoot":"","sources":["../src/blocks.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"blocks.d.ts","sourceRoot":"","sources":["../src/blocks.ts"],"names":[],"mappings":"AACA,OAAO,EAAsC,KAAK,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC9E,OAAO,EAAa,KAAK,UAAU,EAAU,MAAM,aAAa,CAAC;AAajE,gGAAgG;AAChG,MAAM,WAAW,OAAO;IACvB,OAAO,CAAC,EAAE,UAAU,CAAC;IACrB,qDAAqD;IACrD,MAAM,CAAC,EAAE,UAAU,CAAC;CACpB;AAWD,kGAAkG;AAClG,wBAAgB,SAAS,CAAC,GAAG,KAAK,EAAE,UAAU,EAAE,GAAG,QAAQ,CAI1D;AAED,0GAA0G;AAC1G,wBAAgB,OAAO,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,GAAG,KAAK,EAAE,UAAU,EAAE,GAAG,QAAQ,CAMtF;AAED,uBAAuB;AACvB,eAAO,MAAM,EAAE,GAAI,GAAG,OAAO,UAAU,EAAE,KAAG,QAAgC,CAAC;AAC7E,uBAAuB;AACvB,eAAO,MAAM,EAAE,GAAI,GAAG,OAAO,UAAU,EAAE,KAAG,QAAgC,CAAC;AAC7E,uBAAuB;AACvB,eAAO,MAAM,EAAE,GAAI,GAAG,OAAO,UAAU,EAAE,KAAG,QAAgC,CAAC;AAC7E,uBAAuB;AACvB,eAAO,MAAM,EAAE,GAAI,GAAG,OAAO,UAAU,EAAE,KAAG,QAAgC,CAAC;AAC7E,uBAAuB;AACvB,eAAO,MAAM,EAAE,GAAI,GAAG,OAAO,UAAU,EAAE,KAAG,QAAgC,CAAC;AAC7E,uBAAuB;AACvB,eAAO,MAAM,EAAE,GAAI,GAAG,OAAO,UAAU,EAAE,KAAG,QAAgC,CAAC;AAE7E;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,QAAQ,CAOtE;AAED,qFAAqF;AACrF,wBAAgB,MAAM,CAAC,GAAG,KAAK,EAAE,UAAU,EAAE,GAAG,QAAQ,CAEvD;AAED,4CAA4C;AAC5C,wBAAgB,OAAO,IAAI,QAAQ,CAElC;AAED,oHAAoH;AACpH,wBAAgB,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,QAAQ,CAMtD;AAED,2EAA2E;AAC3E,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAElD;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,EAAE,EAAE,MAAM,CAAC,EAAE,UAAU,GAAG,QAAQ,CAmB7E;AAED,qGAAqG;AACrG,wBAAgB,SAAS,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,UAAU,GAAG,QAAQ,CAKzE;AAgBD,sFAAsF;AACtF,wBAAgB,OAAO,CAAC,MAAM,EAAE,UAAU,EAAE,EAAE,OAAO,GAAE,OAAY,GAAG,QAAQ,CAE7E;AAED,0FAA0F;AAC1F,wBAAgB,SAAS,CAAC,MAAM,EAAE,UAAU,EAAE,EAAE,OAAO,GAAE,OAAY,GAAG,QAAQ,CAE/E;AAID,QAAA,MAAM,UAAU,eAAuC,CAAC;AAExD,MAAM,WAAW,gBAAgB;IAChC,sFAAsF;IACtF,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,yCAAyC;IACzC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,yCAAyC;IACzC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+FAA+F;IAC/F,KAAK,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;IACpC,wEAAwE;IACxE,MAAM,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,QAAQ,CAAC;CACrC;AAED,kGAAkG;AAClG,MAAM,WAAW,SAAU,SAAQ,QAAQ;IAC1C,QAAQ,CAAC,CAAC,UAAU,CAAC,EAAE,IAAI,CAAC;IAC5B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;CAC7C;AAUD,gGAAgG;AAChG,wBAAgB,IAAI,CAAC,OAAO,CAAC,EAAE,UAAU,EAAE,OAAO,GAAE,gBAAqB,GAAG,SAAS,CAmBpF;AAED,MAAM,WAAW,YAAY;IAC5B,kEAAkE;IAClE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,uFAAuF;IACvF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,+DAA+D;IAC/D,OAAO,CAAC,EAAE,UAAU,CAAC;CACrB;AAQD;;;;;;GAMG;AACH,wBAAgB,KAAK,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,OAAO,GAAE,YAAiB,GAAG,QAAQ,CAqBhF;AAED,MAAM,WAAW,cAAc;IAC9B,oFAAoF;IACpF,IAAI,CAAC,EAAE,OAAO,CAAC;CACf;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CACtB,OAAO,EAAE,UAAU,EACnB,MAAM,EAAE,UAAU,EAAE,EACpB,OAAO,GAAE,cAAmB,GAC1B,QAAQ,CAQV;AAID,QAAA,MAAM,SAAS,eAAsC,CAAC;AAEtD,MAAM,WAAW,eAAe;IAC/B,4FAA4F;IAC5F,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,iHAAiH;IACjH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sGAAsG;IACtG,IAAI,CAAC,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;CAC7B;AAED,0FAA0F;AAC1F,MAAM,WAAW,QAAS,SAAQ,QAAQ;IACzC,QAAQ,CAAC,CAAC,SAAS,CAAC,EAAE,IAAI,CAAC;IAC3B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACxB;AAUD,qGAAqG;AACrG,wBAAgB,IAAI,CAAC,MAAM,EAAE,UAAU,EAAE,EAAE,OAAO,GAAE,eAAoB,GAAG,QAAQ,CAoBlF;AAED,MAAM,WAAW,WAAW;IAC3B,qDAAqD;IACrD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,sFAAsF;IACtF,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;GAIG;AACH,wBAAgB,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,EAAE,OAAO,GAAE,WAAgB,GAAG,QAAQ,CAsB/E;AAID,MAAM,WAAW,UAAU;IAC1B,sCAAsC;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CACf;AAED;;;;GAIG;AACH,wBAAgB,GAAG,CAClB,QAAQ,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,EACjD,OAAO,EAAE,UAAU,EACnB,OAAO,GAAE,OAAY,GACnB,QAAQ,CAMV;AAED,MAAM,WAAW,YAAa,SAAQ,OAAO;IAC5C,6DAA6D;IAC7D,OAAO,CAAC,EAAE,OAAO,CAAC;CAClB;AAsBD;;;;GAIG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,GAAG,QAAQ,CAEvE;AAED;;;;GAIG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,GAAG,QAAQ,CAEvE;AAED;;;;GAIG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,GAAG,QAAQ,CAEvE;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,GAAG,KAAK,EAAE,UAAU,EAAE,GAAG,QAAQ,CAEzD;AAID;;;;GAIG;AACH,wBAAgB,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,EAAE,SAAS,GAAE,UAAe,GAAG,QAAQ,CAQhF"}